# -*- coding: utf-8 -*-


import hashlib
import hmac
import time
import urllib.request, urllib.error, urllib.parse
from urllib.parse import quote

import requests
from qcloud_cos import CosConfig, CosS3Auth
from qcloud_cos import CosS3Client

from django.conf import settings
from functools import reduce

from config.settings.base import logger

QCLOUD_COS_BUCKET = settings.AWS_STORAGE_BUCKET_NAME
COS_SECRET_ID = settings.AWS_ACCESS_KEY_ID
SECRET_KEY = settings.AWS_SECRET_ACCESS_KEY
AWS_S3_REGION_NAME = settings.AWS_S3_REGION_NAME


class ObjectCloudSave(object):
    '''
    对象云存储
    目前采用腾讯云，官方提供了sdk
    '''

    # appid已在配置中移除,请在参数Bucket中带上appid。Bucket由bucketname-appid组成
    # 1. 设置用户配置, 包括 secretId，secretKey 以及 Region
    secret_id = COS_SECRET_ID
    secret_key = SECRET_KEY
    region = AWS_S3_REGION_NAME
    token = ''  # 使用临时密钥需要传入 Token，默认为空，可不填
    config = CosConfig(Secret_id=secret_id, Secret_key=secret_key, Region=region, Token=token)

    # 2. 获取客户端对象
    client = CosS3Client(config)

    @classmethod
    def get_auth(cls, method, pathname, secret_id, secret_key):
        config = CosConfig(Secret_id=secret_id, Secret_key=secret_key, Region=cls.region, Token=cls.token)
        client = CosS3Client(config)
        response = client.get_auth(
            Method=method,
            Bucket=QCLOUD_COS_BUCKET,
            Key=pathname,
            Expired=300,
            Headers={},
            Params={}
        )
        return response

    @classmethod
    def delete_object(cls, src):
        """
        @author: fenghuan
        @param src: 图片在服务器上的链接url
        """
        root_url = cls.get_root_url()
        file_key = src.split(root_url)[-1]
        response = cls.client.delete_object(
            Bucket=QCLOUD_COS_BUCKET,
            Key=file_key
        )
        return response

    @classmethod
    def get_root_url(cls):
        return cls.client._conf.uri(bucket=QCLOUD_COS_BUCKET)


class Sts:

    POLICY = r'''{"statement": [{"action": ["name/cos:*"],"effect": "allow","resource":"*"}],"version": "2.0"}'''
    DURATION = 1800

    def __init__(self, config = {}):
        if 'policy' in config:
            self.policy = config.get('policy')
        else:
            self.policy = self.POLICY

        if 'duration_in_seconds' in config:
            self.duration = config.get('duration_in_seconds')
        else:
            self.duration = self.DURATION

        self.secret_id = config.get('secret_id')
        self.secret_key = config.get('secret_key')
        self.proxy = config.get('proxy')

    def get_credential(self):
        try:
            import ssl
        except ImportError:
            logger.error("error: no ssl support")

        policy = self.policy
        secret_id = self.secret_id
        secret_key = self.secret_key
        duration = self.duration
        real_url = self.__get_url(policy, duration, secret_id, secret_key)
        try:
            response = requests.get(real_url, proxies=self.proxy)
            return response
        except urllib.error.HTTPError as e:
            logger.error("error with : " + e)

    def __get_url(self, policy, duration, secret_id, secret_key, name=''):
        method = 'GET'
        path = 'sts.api.qcloud.com/v2/index.php'
        scheme = 'https://'

        params = {'Action': 'GetFederationToken',
                  'codeMode': 'base64',
                  'Nonce': str(int(time.time()) % 1000000),
                  'Region': '',
                  'RequestClient': 'tac-storage-python',
                  'SecretId': secret_id,
                  'Timestamp': str(int(time.time())),
                  'name': name,
                  'policy': policy,
                  'durationSeconds': str(duration)
                  }

        sign = self.__encrypt(method, path, params)
        params['Signature'] = sign
        flat_params_str = Tools.flat_params(params)

        return scheme + path + '?' + flat_params_str

    def __encrypt(self, method, path, key_values):
        source = Tools.flat_params(key_values)
        source = method + path + '?' + source
        sign = hmac.new(self.secret_key, source, hashlib.sha1).digest().encode('base64').rstrip()
        return quote(sign)


class Tools(object):

    @staticmethod
    def _flat_key_values(a):
        return a[0] + '=' + a[1]

    @staticmethod
    def _link_key_values(a, b):
        return a + '&' + b

    @staticmethod
    def flat_params(key_values):
        key_values = sorted(iter(key_values.items()), key=lambda d: d[0])
        return reduce(Tools._link_key_values, list(map(Tools._flat_key_values, key_values)))
